package com.moyun.modelclass.http;

import static com.blankj.utilcode.util.CacheDoubleStaticUtils.put;

import android.app.Activity;
import android.content.Context;
import android.util.Log;

import androidx.lifecycle.LifecycleOwner;

import com.alibaba.sdk.android.oss.ClientConfiguration;
import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSS;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.common.OSSLog;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSFederationToken;
import com.alibaba.sdk.android.oss.common.auth.OSSStsTokenCredentialProvider;
import com.alibaba.sdk.android.oss.internal.OSSAsyncTask;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectResult;
import com.blankj.utilcode.util.FileUtils;
import com.hjq.http.EasyHttp;
import com.hjq.http.listener.HttpCallback;
import com.hjq.http.listener.OnHttpListener;
import com.moyun.modelclass.http.api.GenerateStsTokenApi;
import com.moyun.modelclass.http.model.HttpData;
import com.tencent.mmkv.MMKV;

import java.util.HashMap;

public class OSSHelper {
    private static volatile OSSHelper INSTANCE;
    private OSS mOSS;
    protected MMKV kv;
    private OnOssUpLoadStateListener mOnOssUpLoadStateListener;
    private String mEndpoint = "http://oss-cn-hangzhou.aliyuncs.com";

    public static OSSHelper getInstance(OnOssUpLoadStateListener onOssUpLoadStateListener) {
        if (INSTANCE == null) {
            synchronized (OSSHelper.class) {
                if (INSTANCE == null)
                    INSTANCE = new OSSHelper(onOssUpLoadStateListener);
            }
        }
        return INSTANCE;
    }

    private OSSHelper(OnOssUpLoadStateListener onOssUpLoadStateListener) {
        this.mOnOssUpLoadStateListener = onOssUpLoadStateListener;
    }

    public boolean isInit() {
        return mOSS != null;
    }

    public synchronized void init(Activity activity, boolean isOther, String extension, String stlPath, long fileSize) {
        kv = MMKV.defaultMMKV();
        EasyHttp.post((LifecycleOwner) activity)
                .api(new GenerateStsTokenApi().setFileSize((int) fileSize).setOther(isOther))
                .request(new HttpCallback<HttpData<GenerateStsTokenApi.Bean>>((OnHttpListener) activity) {
                    @Override
                    public void onSucceed(HttpData<GenerateStsTokenApi.Bean> stlResult) {
                        if (stlResult == null || stlResult.getData() == null) {
                            return;
                        }
                        OSSCredentialProvider credentialProvider = newStsTokenCredentialProvider(stlResult.getData().getAccessKeyId(),
                                stlResult.getData().getAccessKeySecret(),
                                stlResult.getData().getSecurityToken(),
                                stlResult.getData().getExpiration());
                        ClientConfiguration conf = new ClientConfiguration();
                        conf.setConnectionTimeout(15 * 1000); // 连接超时，默认15秒
                        conf.setSocketTimeout(15 * 1000); // socket超时，默认15秒
                        conf.setMaxConcurrentRequest(5); // 最大并发请求书，默认5个
                        conf.setMaxErrorRetry(2); // 失败后最大重试次数，默认2次
                        mOSS = new OSSClient(activity, mEndpoint, credentialProvider, conf);

                        String fileId = stlResult.getData().getFileId();
                        String fileUrl = stlResult.getData().getFileDir() + "/" + stlResult.getData().getObjectKey();

                        PutObjectRequest put = new PutObjectRequest(stlResult.getData().getBucketName(), fileUrl, stlPath);      // 构造上传请求。

                        put.setCallbackParam(new HashMap<String, String>() {
                            {
                                put("callbackUrl", stlResult.getData().getCallbackServer());
                                put("callbackBody", "bucket=${bucket}&object=${object}&etag=${etag}&size=${size}&userId=${x:userId}&fileName=${x:fileName}&fileId=${x:fileId}");
                            }
                        });
                        put.setCallbackVars(new HashMap<String, String>() {
                            {
                                put("x:userId", CommonConfiguration.getUseId(kv));
                                put("x:fileName", FileUtils.getFileName(stlPath));
                                put("x:fileId", fileId);
                            }
                        });

                        OSSAsyncTask<PutObjectResult> task = mOSS.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
                            @Override
                            public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                                if (mOnOssUpLoadStateListener != null) {
                                    mOnOssUpLoadStateListener.onSuccess(request, result, fileId, fileUrl);
                                }
//                                ToastUtils.showShort("上传成功");
                                Log.d("PutObject", "UploadSuccess");
                                Log.d("ETag", result.getETag());
                                Log.d("RequestId", result.getRequestId());
                            }

                            @Override
                            public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {
                                if (mOnOssUpLoadStateListener != null) {
                                    mOnOssUpLoadStateListener.onFailure(request, clientException, serviceException);
                                }
                                // 请求异常。
                                if (clientException != null) {
                                    // 本地异常，如网络异常等。
                                    clientException.printStackTrace();
                                }
                                if (serviceException != null) {
                                    // 服务异常。
                                    Log.e("ErrorCode", serviceException.getErrorCode());
                                    Log.e("RequestId", serviceException.getRequestId());
                                    Log.e("HostId", serviceException.getHostId());
                                    Log.e("RawMessage", serviceException.getRawMessage());
                                }
                            }
                        });
//                        task.cancel(); // 可以取消任务。
                        task.waitUntilFinished(); // 等待上传完成。
                    }
                });

    }

    public static OSSCredentialProvider newStsTokenCredentialProvider(String accessKeyId, String accessKeySecret, String securityToken, String expiration) {
        try {
            return new OSSStsTokenCredentialProvider(new OSSFederationToken(accessKeyId, accessKeySecret, securityToken, expiration));
        } catch (Exception e) {
            OSSLog.logError(e.toString());
            e.printStackTrace();
            return new OSSStsTokenCredentialProvider("", "", "");
        }
    }

    public interface OnOssUpLoadStateListener {
        void onSuccess(PutObjectRequest request, PutObjectResult result, String fileId, String fileUrl);

        void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException);
    }

    public void delete() {
        INSTANCE = null;
    }
}
